package org.rest
import grails.converters.JSON
import grails.converters.XML

class ProductController {
	
	def list = { 
		def products = Product.list()
		response.setHeader("Content-Location",g.createLink(controller:"product",absolute:"true") as String)
		if (products.isEmpty()){
			response.status = 204
			render ""
		} else {
			response.status = 200
			withFormat {
				 xml { render(contentType:"text/xml"){
							elements{ products.each {p ->
									product {
										uri(g.createLink(controller:"product",id:(p.id),absolute:"true"))
										uri(g.createLink(controller:"categories",id:(p?.category?.id),absolute:"true"))
										uri(g.createLink(controller:"suppliers",id:(p?.supplier?.id),absolute:"true"))
										discontinued(p.discontinued)
										name(p.name)
										quantityPerUnit(p.quantityPerUnit)
										reorderLevel(p.reorderLevel)
									    unitInStock(p.unitInStock)
										unitOnOrders(p.unitOnOrders)
										unitPrice(p.unitPrice)	
									}
								}                       
							}   
						}
				 }
	     	}
	    }
	}
	
	def show = {
		def p = Product.get(params.id)
		if (p) {
			response.setHeader("Content-Location",g.createLink(controller:"product",id:params.id,absolute:"true") as String)
			withFormat {
				xml  { 
					render(contentType:"text/xml"){
								product{
									uri(g.createLink(controller:"categories",id:(p?.category?.id),absolute:"true"))
									uri(g.createLink(controller:"suppliers",id:(p?.supplier?.id),absolute:"true"))
									discontinued(p.discontinued)
									name(p.name)
									quantityPerUnit(p.quantityPerUnit)
									reorderLevel(p.reorderLevel)
									unitInStock(p.unitInStock)
									unitOnOrders(p.unitOnOrders)
									unitPrice(p.unitPrice)	
								}
							}                       
						   
					}
			}
		} else {
			sendNotFoundResponse()
		}
	}	
	
	def create = {
		def p = new Product()
		def xml = request.XML
		updateInternal(p,xml)
		if (p.validate()) {
			p.save(flush:true);
			response.status = 201
			response.setHeader("Content-Location",g.createLink(controller:"product",id:p.id,absolute:"true") as String)
			render(contentType:"text/xml"){
						 product{
							uri(g.createLink(controller:"categories",id:(p?.category?.id),absolute:"true"))
							uri(g.createLink(controller:"suppliers",id:(p?.supplier?.id),absolute:"true"))
							discontinued(p.discontinued)
							name(p.name)
							quantityPerUnit(p.quantityPerUnit)
							reorderLevel(p.reorderLevel)
							unitInStock(p.unitInStock)
							unitOnOrders(p.unitOnOrders)
							unitPrice(p.unitPrice)	
						}
					}                       
		 } else {
			sendErrorResponse(p, 403)
		}
	} 	
	
	def delete = {
		def product = Product.get(params.id)
		if (!product) {
			sendNotFoundResponse()
		}
		product.delete();
		response.status = 204
		render ""
	}
	
	def update = {
		def p = Product.get(params.id)
		def xml = request.XML
		if (!p) {
			sendNotFoundResponse()
		}
		updateInternal(p,xml)
		if (p.validate()) {
			p.save(flush:true);
			response.setHeader("Content-Location",g.createLink(controller:"product",id:params.id,absolute:"true") as String)
			render(contentType:"text/xml"){
					product{
						uri(g.createLink(controller:"categories",id:(p?.category?.id),absolute:"true"))
						uri(g.createLink(controller:"suppliers",id:(p?.supplier?.id),absolute:"true"))
						discontinued(p.discontinued)
						name(p.name)
						quantityPerUnit(p.quantityPerUnit)
						reorderLevel(p.reorderLevel)
						unitInStock(p.unitInStock)
						unitOnOrders(p.unitOnOrders)
						unitPrice(p.unitPrice)	
						}
					}                       
			
			 
		} else {
			sendErrorResponse(p, 403)
		}
	} 
	
	
	private def updateInternal(p,xml){
		p.name = xml.name.text()
		p.quantityPerUnit = xml.quantityPerUnit.text() as int
		p.unitPrice = xml.unitPrice.text() as double
		p.unitInStock = xml.unitInStock.text() as int
		p.unitOnOrders = xml.unitOnOrders.text() as int
		p.reorderLevel = xml.reorderLevel.text()
		p.discontinued = xml.discontinued.text() as boolean
		p.supplier     = Suppliers.get(xml.supplier.text())
		p.category	   = Categories.get(xml.category.text())
	}
	
	
	
	private def sendErrorResponse(product, status) {
		response.status = status
		render contentType: "application/xml", {
			errors {
				product?.errors?.fieldErrors?.each {err ->
					field(err.field)
					message(g.message(error: err))
				}
			}
		}
	}
	
	
	private def sendNotFoundResponse() {
		response.status = 404
		render contentType: "application/xml", {
			errors {
				message("Product not found with id: " + params.id)
			}
		}
	}
	
}